`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date:    14:11:49 04/06/2012 
// Design Name: 
// Module Name:    AxiLite2RP 
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//////////////////////////////////////////////////////////////////////////////////
module AxiLite2RP(
  input           CLK,
  input           RST,

  input   [31:0]  S_AWADDR,
  input           S_AWVALID,
  output          S_AWREADY,
  input   [31:0]  S_WDATA,
  input   [3:0]   S_WSTRB,
  input           S_WVALID,
  output          S_WREADY,
  output  [1:0]   S_BRESP,
  output          S_BVALID,
  input           S_BREADY,
  input   [31:0]  S_ARADDR,
  input           S_ARVALID,
  output          S_ARREADY,
  output  [31:0]  S_RDATA,
  output  [1:0]   S_RRESP,
  output          S_RVALID,
  input           S_RREADY,

  output          RP_EN,
  output  [3:0]   RP_WE,
  output  [5:0]   RP_A,
  input   [31:0]  RP_RD,
  output  [31:0]  RP_WD,
  input           RP_RDY
  );
  
`define OKAY    2'b00
`define SLVERR  2'b10

  localparam
    IDLE = 0,
    AR = 1,
    R = 2,
    AW = 3,
    W = 4,
    B = 5,
    WAW = 6,
    W_WAIT = 7,
    AW_WAIT = 8,
    READ = 9,
    WRITE = 10;
    
  reg [3:0] rState, sState;
  reg TimeOut;
  reg [31:0] rAddr;
  reg [31:0] rWData;
  reg [31:0] rRData;
  reg [3:0] rWStrb;
  reg [3:0] rTimer;

  always @(posedge CLK)
  begin
    if (RST)
      rState <= IDLE;
    else
      rState <= sState;
  end
  
  always @*
  begin
    sState <= rState;
    case (rState)
      IDLE:
        if (S_ARVALID)
          sState <= AR;
        else if (S_AWVALID && S_WVALID)
          sState <= WAW;
        else if (S_AWVALID)
          sState <= AW;
        else if (S_WVALID)
          sState <= W;
      AR:
        sState <= READ;
      R:
        if (S_RREADY)
          sState <= IDLE;
      AW:
        sState <= W_WAIT;
      W:
        sState <= AW_WAIT;
      B:
        if (S_BREADY)
          sState <= IDLE;
      WAW:
        sState <= WRITE;
      W_WAIT:
        if (S_WVALID)
          sState <= WRITE;
      AW_WAIT:
        if (S_AWVALID)
          sState <= WRITE;
      READ:
        if (RP_RDY || TimeOut)
          sState <= R;
      WRITE:
        if (RP_RDY || TimeOut)
          sState <= B;
    endcase
  end
  
  always @(posedge CLK)
  begin
    if (S_ARVALID && S_ARREADY)
      rAddr <= S_ARADDR;
    else if (S_AWVALID && S_AWREADY)
      rAddr <= S_AWADDR;
  end
  
  always @(posedge CLK)
  begin
    if (S_WVALID && S_WREADY)
    begin
      rWData <= S_WDATA;
      rWStrb <= S_WSTRB;
    end
  end
  
  always @(posedge CLK)
  begin
    if (RP_RDY)
      rRData <= RP_RD;
  end
  
  always @(posedge CLK)
  begin
    if (!RP_EN)
    begin
      rTimer <= 0;
      TimeOut <= 1'b0;
    end
    else
    begin
      rTimer <= rTimer + 1;
      if (rTimer == 4'hF)
        TimeOut <= 1'b1;
    end
  end
  
  assign S_ARREADY = (rState == AR);
  assign S_AWREADY = (rState == WAW) || (rState == AW) || (rState == AW_WAIT);
  assign S_WREADY = (rState == WAW) || (rState == W) || (rState == W_WAIT);
  assign S_RVALID = (rState == R);
  assign S_BVALID = (rState == B);
  assign S_RDATA = (rState == R) ? (TimeOut ? 32'hBAD0ADD0 : rRData) : 32'h0;
  assign S_RRESP = ((rState == R) && TimeOut) ? `SLVERR : `OKAY;
  assign S_BRESP = ((rState == B) && TimeOut) ? `SLVERR : `OKAY;
  
  assign RP_EN = (rState == READ) || (rState == WRITE);
  assign RP_WE = (rState == WRITE) ? rWStrb : 4'b0;
  assign RP_WD = rWData;
  assign RP_A = (rAddr >> 2);
endmodule
